import React, { useEffect, useState, Key } from 'react'
import { useNavigate } from 'react-router-dom'
import {
  Button,
  Form,
  Input,
  Space,
  Card,
  Table,
  Tooltip,
  Modal,
  message,
} from 'antd'
import type { ColumnsType } from 'antd/es/table'

import {
  SearchOutlined,
  EditOutlined,
  DeleteOutlined,
  ExclamationCircleOutlined,
} from '@ant-design/icons'

// 引入发送请求的函数
import {
  reqGetHospitalSets,
  reqDelHospitalSet,
  reqBatchDelHospitalSets,
} from '@api/hospitalSet'

// 引入ts类型
import {
  IhospitalSetList,
  IhospitalSet,
} from '@api/hospitalSet/model/hospitalSetTypes'

// 定义变量,用来记录用户是否点击了查询按钮
let flag = false // true表示点击了,false表示没有点击
export default function HospitalSet() {
  // 获取编程式导航navigate函数
  const navigate = useNavigate()
  //  创建form实例
  const [form] = Form.useForm()
  // 定义存储表格数据的状态
  // 这个data用来存储表格中要渲染的那个数组
  // 注意: useState调用时可以通过泛型传入当前状态数据的类型
  const [data, setData] = useState<IhospitalSetList>([])
  // 存储数据总数的状态
  const [total, setTotal] = useState(0)
  // 一页几条数据的状态
  const [pageSize, setPageSize] = useState(2)
  // 控制页码高亮的状态
  const [page, setPage] = useState(1)

  // 请求表格数据展示的正在加载效果状态
  const [loading, setLoading] = useState(false)

  // (主要存储了选中的数据的id)控制批量删除按钮是否禁用的状态
  const [RowKeys, setRowKeys] = useState<Key[]>([])
  // 注意: useEffect的回调不允许定义为异步函数
  useEffect(() => {
    // 组件挂载的时候获取表格数据
    getHospitalSets(page, pageSize)
  }, [])

  // 分页器的change事件
  function onChange(page: number, pageSize: number) {
    // 只要操作了分页器,这个事件就会触发
    // page是当前用户选择的页数
    // pageSize是当前用户选择的一页几条
    setPageSize(pageSize)
    setPage(page)

    // 发送请求获取表格数据
    getHospitalSets(page, pageSize)
  }

  // 有表单校验的时候,则表单校验通过才触发.没有表单校验的时候,只要点击了提交按钮就直接触发
  const onFinish = (values: any) => {
    flag = true //先把flag设置为true
    // console.log('Success:', values)
    setPage(1) //让分页器的第一页高亮
    getHospitalSets(1, pageSize)
  }

  // 清空按钮的事件处理函数
  function clearForm() {
    // 清空表单
    form.setFieldsValue({ hosname: '', hoscode: '' })
    flag = false
    getHospitalSets(1, pageSize)
    setPage(1) //让分页器的第一页高亮
  }

  // 批量删除数据的事件处理函数
  function batchDelHospitalSet() {
    // 1. 弹出模态框
    Modal.confirm({
      title: '确定要批量删除数据吗?',
      icon: <ExclamationCircleOutlined />,
      async onOk() {
        // 2. 点击确认发送请求删除数据
        await reqBatchDelHospitalSets(RowKeys)
        // 3. 刷新页面
        getHospitalSets(page, pageSize)
        // 4. 提示用户
        message.success('批量删除成功')
      },
    })
  }
  async function getHospitalSets(page: number, pageSize: number) {
    setLoading(true) // 展示loading
    // 想办法直接获取到表单中的hosname和hoscode,然后直接传入reqGetHospitalSets函数
    // 利用Form组件提供的form实例获取表单数据
    // 1. 创建form实例
    // 2. 将创建好的form实例和要操作的Form组件进行绑定
    // 3. form.getFieldsValue() 返回绑定的Form表单中所有写了name属性的表单元素的值
    const { hosname, hoscode } = form.getFieldsValue()
    // 判断,如果点击了查询按钮,才添加hosname和hoscode.如果没有点击查询按钮,就不添加hosname和hoscode
    let result
    if (flag) {
      // 点击了查询
      result = await reqGetHospitalSets(page, pageSize, hosname, hoscode)
    } else {
      // 没有点击查询
      result = await reqGetHospitalSets(page, pageSize)
    }

    setLoading(false) //隐藏loading
    // 修改状态data
    setData(result.records)
    // 问题1: records下面有红色波浪线.说result的类型中没有records(解决: 在封装发请求的函数位置传入泛型)
    // 问题2: result.records下面有红色波浪线.说不能把响应数据的类型赋值给never(解决: 在定义状态的时候,传入泛型)
    // 存储数据总数
    setTotal(result.total)
  }
  // columns这个数组决定了表格的列
  // 这里ColumnsType是描述columns的类型
  // ColumnsType<泛型> 泛型是描述dataSource的数据类型.注意要的是dataSource这个数组中的对象的数据类型
  const columns: ColumnsType<IhospitalSet> = [
    {
      // title决定了这一列的标题
      title: '序号',
      // 如果写了render,则dataIndex只决定了render函数的第一个参数
      // 如果不写render,则dataIndex决定了这一列渲染什么数据
      // dataIndex: 'name',
      // key: 'name', // key是每一列数据的key值(没用)
      // 如果写了render,则render函数的返回值,决定了这一列渲染什么数据
      render: (a, b, c) => {
        // console.log(a, b, c)

        // 表格渲染几条数据,则render执行几次
        // a的值会变化. a的值受dataIndex属性的影响. 没写dataIndex,则a和b是一样的.如果写的dataIndex,则a的值就是dataIndex后面写的对应的属性的值
        // b的值不变, 永远是表格渲染的数据
        // c的值不变, 永远是表格渲染的数据的下标

        return c + 1
      },

      align: 'center', // 让这一列的内容水平居中
      width: 80, // 控制这一列的宽度.单位是px
    },
    {
      title: '医院名称',
      dataIndex: 'hosname',
    },
    {
      title: '医院编号',
      dataIndex: 'hoscode',
    },
    {
      title: 'api基础路径',
      dataIndex: 'apiUrl',
    },
    {
      title: '签名',
      dataIndex: 'signKey',
    },
    {
      title: '联系人名称',
      dataIndex: 'contactsName',
    },
    {
      title: '联系人手机号',
      dataIndex: 'contactsPhone',
    },
    {
      title: '操作',
      dataIndex: 'id',
      render(id) {
        return (
          <Space>
            <Tooltip title="修改医院">
              <Button
                icon={<EditOutlined />}
                type="primary"
                onClick={() => {
                  navigate(`/syt/hospital/hospitalSet/edit/${id}`)
                }}
              ></Button>
            </Tooltip>
            <Tooltip title="删除医院">
              <Button
                icon={<DeleteOutlined />}
                danger
                type="primary"
                onClick={() => {
                  // 1. 先弹出模态框(Dialog),询问用户是否删除
                  Modal.confirm({
                    // title就是模态框的标题
                    title: '确定要删除这条医院设置数据吗?',
                    icon: <ExclamationCircleOutlined />,
                    // content 就是模态框的内容
                    // content:
                    //   'When clicked the OK button, this dialog will be closed after 1 second',
                    // onOk 就是模态框中确认按钮的事件处理函数
                    async onOk() {
                      // 2. 用户点击确认按钮,则发送请求删除数据
                      await reqDelHospitalSet(id)
                      // 3. 删除成功,刷新页面
                      getHospitalSets(page, pageSize)
                    },
                    //onCancel 就是模态框中取消按钮的事件处理函数
                    // onCancel() {},
                  })
                }}
              ></Button>
            </Tooltip>
          </Space>
        )
      },

      width: 100,
      fixed: 'right', //这一列固定到右侧
    },
  ]
  return (
    <Card>
      <Form
        //  只要用户在表单中输入内容了,导致了写了name属性的表单元素的值发生变化,事件就会触发
        onValuesChange={() => {
          // 限制用户,用户只要在表单中输入内容,就必须点击查询.否则输入的内容不会参与到筛选条件中
          flag = false
        }}
        form={form} // 绑定form实例和Form组件
        // layout="inline" 表示让表单中的每一个表单元素在一行显示.放不下会自动换行
        layout="inline"
        name="basic" // 表单的名称,用于区分表单
        // antd中默认进行了栅格布局.一行分为了24份
        // labelCol代表了表单中的提示文本部分. span表示在一行中占多少份
        // labelCol={{ span: 2 }}
        // wrapperCol代表了表单中的表单元素部分
        // wrapperCol={{ span: 22 }}
        // 设置表单中指定表单元素的初始值
        // remember：true。 表示将name属性值为remember的表单元素初始值设置为true
        // initialValues={{ remember: true }}
        // 点击了表单的提交按钮,如果表单校验通过了,则触发onFinish
        onFinish={onFinish}
        // 点击了表单的提交按钮,如果表单校验不通过了,则触发onFinishFailed
        // onFinishFailed={onFinishFailed}
        // autoComplete="off"
      >
        {/* antd的表单中的表单元素应该被Form.Item包裹,目的是为了方便控制表单元素 */}
        <Form.Item
          // label决定了当前表单元素的提示文本
          // label="嘻嘻嘻"
          // 表单元素的name
          name="hosname"
          // 设置当前表单元素的校验规则
          // required:true表示当前表单元素为必填项
          // message是当表单校验不通过时的提示信息
          // rules={[{ required: false, message: 'Please input your username!' }]}
        >
          <Input placeholder="医院名称" />
        </Form.Item>

        <Form.Item
          // label="Password"
          name="hoscode"
          // rules={[{ required: true, message: 'Please input your password!' }]}
        >
          <Input placeholder="医院编码" />
        </Form.Item>

        {/* <Form.Item
          name="remember"
          // Form.Item默认控制包裹的表单元素的value属性. valuePropName="checked" 表示,当前表单元素应该控制的是checked属性
          valuePropName="checked"
          // offset表示当前表单元素的左偏移量
          wrapperCol={{ offset: 0, span: 16 }}
        >
          <Checkbox>Remember me</Checkbox>
        </Form.Item> */}

        <Form.Item>
          {/* Space可以给它所包裹的组件添加间隔距离 */}
          <Space>
            {/* Button的type为primary就是这事一个主题颜色按钮 */}
            {/* htmlType="submit" 表示当前按钮是当前表单的提交按钮 */}
            <Button type="primary" htmlType="submit" icon={<SearchOutlined />}>
              查询
            </Button>
            <Button onClick={clearForm}>清空</Button>
          </Space>
        </Form.Item>
      </Form>

      <Space style={{ marginTop: 20, marginBottom: 20 }}>
        <Button
          type="primary"
          onClick={() => {
            navigate('/syt/hospital/hospitalSet/add')
          }}
        >
          添加
        </Button>
        <Button
          type="primary"
          danger
          disabled={!RowKeys.length}
          onClick={batchDelHospitalSet}
        >
          批量删除
        </Button>
      </Space>

      {/* 
      
      columns决定了一个表格有几列 
      dataSource 决定了表格中渲染的数据 
      bordered 给表格添加边框
      rowSelection 让表格渲染复选框
      scroll表示展示滚动条. x表示水平方向. 1500单位是px.表示滚动距离
      
      */}
      <Table
        // 在table中展示一个正在加载的效果
        loading={loading}
        rowKey={'id'} // 告诉table组件,列表渲染数据时,直接获取数据的id值作为key值
        columns={columns}
        dataSource={data}
        bordered
        rowSelection={{
          // 当用户选择了表格中的选项复选框时触发
          // onSelect() {
          //   console.log('onSelect触发了')
          // },

          onChange(selectedRowKeys, selectedRows) {
            // console.log('onChange', selectedRowKeys, selectedRows)
            // selectedRowKeys 是一个数组,存储了所有选中的数据的id
            // selectedRows 是一个数组,存储了所有选中的数据对象
            setRowKeys(selectedRowKeys)
          },
        }}
        scroll={{ x: 1500 }}
        // 用来控制表格中的分页器
        pagination={{
          current: page, // current决定了哪个页码高亮
          // 这个配置对象中的属性要去Pagination组件中查看
          total, //数据总数
          pageSize, // 一页几条(默认10条)
          showSizeChanger: true, // 展示修改一页几条的下拉框
          pageSizeOptions: [2, 5, 10], // 自定义修改一页几条下拉框的选项
          showQuickJumper: true, // 快速跳转到指定页

          showTotal(total) {
            // 这个函数的返回值是什么,则分页器前面就展示什么
            return `总共有${total}条数据`
          },
          // 只要操作了分页器,这个事件就会触发
          onChange,
        }}
      />
    </Card>
  )
}
